package com.Lubaichen.Wiki.service;

import com.Lubaichen.Wiki.Exception.BusinessException;
import com.Lubaichen.Wiki.Exception.BusinessExceptionCode;
import com.Lubaichen.Wiki.Pojo.Content;
import com.Lubaichen.Wiki.Pojo.ContentExample;
import com.Lubaichen.Wiki.Pojo.Doc;
import com.Lubaichen.Wiki.Pojo.DocExample;
import com.Lubaichen.Wiki.mapper.CategoryMapper;
import com.Lubaichen.Wiki.mapper.ContentMapper;
import com.Lubaichen.Wiki.mapper.DocMapper;
import com.Lubaichen.Wiki.mapper.MyDocMapper;
import com.Lubaichen.Wiki.req.ContentQueryReq;
import com.Lubaichen.Wiki.req.DocQueryReq;
import com.Lubaichen.Wiki.req.DocSaveReq;
import com.Lubaichen.Wiki.resp.DocQueryResp;
import com.Lubaichen.Wiki.resp.PageResp;
import com.Lubaichen.Wiki.utils.CopyUtil;
import com.Lubaichen.Wiki.utils.RedisUtil;
import com.Lubaichen.Wiki.utils.RequestContext;
import com.Lubaichen.Wiki.utils.SnowFlake;
import com.Lubaichen.Wiki.websocket.WebSocketServer;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
//import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author Lubaichen
 * @date 2022年03月19日 19:54
 */
@Service
public class DocService {
    private static final Logger LOG = LoggerFactory.getLogger(EbookService.class);
    @Resource
    private RedisUtil redisUtil;

    @Autowired
    private DocMapper docMapper;

    @Resource
    private SnowFlake snowFlake;

    @Autowired
    private ContentMapper contentMapper;

    @Resource
    private MyDocMapper myDocMapper;

    @Resource
    private RedisTemplate redisTemplate;

    @Resource
    private WebSocketServer webSocketServer;

    @Resource
    private WebSocketService webSocketService;

//    @Resource
//    private RocketMQTemplate rocketMQTemplate;

    public List<DocQueryResp> all(DocQueryReq req) {
        DocExample docExample = new DocExample();
        DocExample.Criteria criteria = docExample.createCriteria();// Criteria ： 相当于where条件
        docExample.setOrderByClause("sort asc");
        if (!ObjectUtils.isEmpty(req.getName())) {
            criteria.andNameLike("%" + req.getName() + "%");
        }
        List<Doc> categories = docMapper.selectByExample(docExample);
        return CopyUtil.copyList(categories, DocQueryResp.class);
    }

    public List<DocQueryResp> all(Long ebookId) {
        DocExample docExample = new DocExample();
        DocExample.Criteria criteria = docExample.createCriteria();
        criteria.andEbookIdEqualTo(ebookId);
        docExample.setOrderByClause("sort asc");
        List<Doc> docs = docMapper.selectByExample(docExample);
        return CopyUtil.copyList(docs, DocQueryResp.class);
    }


    public PageResp<DocQueryResp> list(DocQueryReq req) {
        DocExample docExample = new DocExample();
        DocExample.Criteria criteria = docExample.createCriteria();// Criteria ： 相当于where条件
        if (!ObjectUtils.isEmpty(req.getName())) {
            criteria.andNameLike("%" + req.getName() + "%");
        }
        // PageHelper只对第一条sql语句生效，如果后面还有sql，那么后面这句sql就没有分页效果。
        PageHelper.startPage(req.getPage(), req.getSize());
        List<Doc> categories = docMapper.selectByExample(docExample);
        PageInfo<Doc> pageInfo = new PageInfo<>(categories);

        LOG.info("总页数:{}", (pageInfo.getPages()));
        LOG.info("总行数:{}", (pageInfo.getTotal()));
        PageResp<DocQueryResp> pageResp = new PageResp<>();
        pageResp.setTotal(pageInfo.getTotal());
        pageResp.setTotal(pageInfo.getTotal());
        pageResp.setList(CopyUtil.copyList(categories, DocQueryResp.class));
        return pageResp;
    }


    @Transactional
    public void save(DocSaveReq req) {
        Doc doc = CopyUtil.copy(req, Doc.class);
        Content content = CopyUtil.copy(req, Content.class);
        if (!ObjectUtils.isEmpty(req.getId())) { // 如果传来的req有id值，那么只进行更新。
            docMapper.updateByPrimaryKey(doc);
            int count = contentMapper.updateByPrimaryKeyWithBLOBs(content);// 包含全部字段（包括大字段）的更新操作
            if (count == 0) {
                contentMapper.insert(content);
            }
        } else { // 如果没有就插入
            doc.setId(snowFlake.nextId()); // 雪花算法生成id
            doc.setViewCount(0);
            doc.setVoteCount(0);
            docMapper.insert(doc);
            content.setId(doc.getId());
            contentMapper.insert(content);
        }
    }


    public void deleteEbookById(Long id) {
        if (!ObjectUtils.isEmpty(id)) {
            docMapper.deleteByPrimaryKey(id);
        }
    }

    public void deleteEbookById(List<Long> ids) {
        DocExample docExample = new DocExample();
        DocExample.Criteria criteria = docExample.createCriteria();
        criteria.andIdIn(ids);
        docMapper.deleteByExample(docExample);
    }


    public List<DocQueryResp> search(DocQueryReq req) {
        DocExample docExample = new DocExample();
        DocExample.Criteria criteria = docExample.createCriteria();
        if (!ObjectUtils.isEmpty(req.getName())) {
            criteria.andNameLike("%" + req.getName() + "%");
        }
        return CopyUtil.copyList(docMapper.selectByExample(docExample), DocQueryResp.class);
    }

    public List<Content> searchDocContent(ContentQueryReq req) {
        ContentExample contentExample = new ContentExample();
        ContentExample.Criteria criteria = contentExample.createCriteria();
        criteria.andIdEqualTo(req.getId());
        List<Content> contents = contentMapper.selectByExample(contentExample);
        return contents;
    }

    public String findContentById(Long id) {
        Content content = contentMapper.selectByPrimaryKey(id);
        // 文档阅读数+1
        myDocMapper.viewCountIncrement(id);
        if (!ObjectUtils.isEmpty(content.getContent())) {
            return content.getContent();
        }
        return "";
    }

    public void voteIncrement(Long id) {
//        String str = ip + id.toString();
//        Object object = redisTemplate.opsForValue().get(ip);
//        if (!ObjectUtils.isEmpty(object)) { // 点赞时效为one day
//            if (object.equals(str)) { // 这个ip已经给id这篇文章点过赞，直接返回
//                return false;
//            }
//            else { // 这个ip给文章点过赞，但是不是给这篇文章点赞的，因此可以给这个文章点赞。
//                myDocMapper.voteCountIncrement(id);
//                redisTemplate.opsForValue().set(ip, str, 3600 * 24, TimeUnit.SECONDS);
//                return true;
//            }
//        } else { // 这个ip没有给文章点过赞,那么可以点赞。
//            myDocMapper.voteCountIncrement(id);
//            redisTemplate.opsForValue().set(ip, str, 3600 * 24, TimeUnit.SECONDS);
//            return true;
//        }
        // doc.id + 远程IP作为key,
        String ip = RequestContext.getRemoteAddr();
        if (redisUtil.validateRepeat("DOC_VOTE_" + id + "_" + ip, 3600 * 12)) {
            myDocMapper.voteCountIncrement(id);
        } else {
            throw new BusinessException(BusinessExceptionCode.VOTE_REPEAT);
        }
        // 推送消息
        Doc docDB = docMapper.selectByPrimaryKey(id);
        String log_id = MDC.get("LOG_ID");
        webSocketService.sendInfo("给[" + docDB.getName() + "]文档点赞成功!", log_id);
//        rocketMQTemplate.convertAndSend("VOTE_TOPIC", "给[" + docDB.getName() + "]文档点赞成功!");
    }

    public void updateEbookInfo() {
        myDocMapper.updateEbookInfo();
    }

}

